﻿using BZ.Core;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace NDK.Motion.Card
{
    [Serializable]
    public class UWC348AIOCard : IOCard
    {
        #region lib
        [DllImport("UWC348Ax64.dll", EntryPoint = "uwc300_initial_x64", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int uwc300_initial_x64(uint COM_Number);

        [DllImport("UWC348Ax64.dll", EntryPoint = "uwc300_close_x64", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int uwc300_close_x64();

        [DllImport("UWC348Ax64.dll", EntryPoint = "uwc300_set_output_x64", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int uwc300_set_output_x64(uint sts);

        [DllImport("UWC348Ax64.dll", EntryPoint = "uwc300_get_output_x64", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int uwc300_get_output_x64(ref char sts);

        [DllImport("UWC348Ax64.dll", EntryPoint = "uwc300_get_input_x64", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int uwc300_get_input_x64(ref char sts);

        [DllImport("UWC348Ax64.dll", EntryPoint = "uwc300_set_16output_x64", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int uwc300_set_16output_x64(uint sts);

        [DllImport("UWC348Ax64.dll", EntryPoint = "uwc300_get_16output_x64", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int uwc300_get_16output_x64(ref uint sts);

        [DllImport("UWC348Ax64.dll", EntryPoint = "uwc300_get_16input_x64", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int uwc300_get_16input_x64(ref uint sts);

        [DllImport("UWC348Ax64.dll", EntryPoint = "uwc300_set_32output_x64", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int uwc300_set_32output_x64(ulong sts);

        [DllImport("UWC348Ax64.dll", EntryPoint = "uwc300_get_32output_x64", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int uwc300_get_32output_x64(ref ulong sts);

        [DllImport("UWC348Ax64.dll", EntryPoint = "uwc300_get_32input_x64", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int uwc300_get_32input_x64(ref ulong sts);

        #endregion

        public bool CardInit(ref List<ICard> cards, int com = 0)
        {
            try
            {
                uwc300_close_x64();
            }
            catch
            { }
            int result = uwc300_initial_x64((uint)com);
            if (0 == result)
            {
                _initialized = true;
                this.CardType = "UWC348A";
                cards.Add(this);
                return true;
            }
            else
            {
                _initialized = false;
                return false;
            }
        }
        public bool CardInit( int com = 0)
        {
            try
            {
                uwc300_close_x64();
            }
            catch
            { }
            int result = uwc300_initial_x64((uint)com);
            if (0 == result)
            {
                _initialized = true;
                return true;
            }
            else
            {
                _initialized = false;
                return false;
            }
        }
        public bool GetDI(int card, int port)
        {
            ulong data = 0;
            int[] diData;
            int result = uwc300_get_32input_x64(ref data);
            if (0 == result)
            {
                diData = new int[24];
                for (int i = 0; i < 24; i++)
                {
                    diData[i] = (int)((data >> i) & 1);
                }
                if (diData[port] == 1)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            else
            {
                throw new IOException($"uwc300_get_32input_x64 Exception,port:{port}");
            }
        }

        public bool GetDO(int card, int port)
        {
            try
            {
                ulong doData = 0;
                int result = uwc300_get_32output_x64(ref doData);
                if (result == 0)
                {
                    UInt32[] doDataChannel = new UInt32[24];
                    for (int i = 0; i < 24; i++)
                    {
                        doDataChannel[i] = (UInt32)((doData >> i) & 1);
                    }

                    if (doDataChannel[port] == 1)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    throw new IOException($"uwc300_get_32output_x64 Fail,port:{port},返回值：{result}");
                }
            }
            catch (Exception ex)
            {
                throw new IOException($"uwc300_get_32output_x64 Exception,port:{port}，异常信息：{ex.StackTrace}");
            }
        }

        public bool SetDO(int card, int port, int ONOrOFF)
        {
            try
            {
                ulong doData = 0;
                int result = uwc300_get_32output_x64(ref doData);

                if (result == 0)
                {
                    UInt32[] doDataChannel = new UInt32[24];
                    for (int i = 0; i < 24; i++)
                    {
                        doDataChannel[i] = (UInt32)((doData >> i) & 1);
                    }

                    doDataChannel[port] = (UInt32)(ONOrOFF == 1 ? 0 : 1);


                    ulong doWrite = 0;
                    for (int j = 0; j < 24; j++)
                    {
                        doWrite = doWrite | (doDataChannel[j] << j);
                    }
                    result = uwc300_set_32output_x64(doWrite);
                    if (result == 0)
                    {
                        return true;
                    }
                    else
                    {
                        throw new IOException($"uwc300_set_32output_x64 Fail,port:{port},返回值：{result}");
                    }
                }
                else
                {
                    throw new IOException($"uwc300_get_32output_x64 Fail,port:{port},返回值：{result}");
                }

            }
            catch (Exception ex)
            {
                throw new IOException($"uwc300_get_32output Exception,port:{port},异常堆栈：{ex.StackTrace}");

            }
        }

        public  bool Finalize()
        {
            try
            {
                if (uwc300_close_x64() == 0)
                {
                    return true;
                }  
            }
            catch (Exception ex)
            {
                throw new IOException($"uwc300_close_x64 Exception,异常堆栈：{ex.StackTrace}");
            }
            return false;
        }

        public void UpdateSlaveResource(ref ICard card, int mode = 0)
        {
            throw new NotImplementedException();
        }

        private string _cardName = "UWC384A";
        public string CardName
        {
            get
            {
                return _cardName;
            }
            set
            {
                _cardName = value;
            }
        }
        private int _cardID = 0;
        public int CardID
        {
            get
            {
                return _cardID;
            }
            set
            {
                _cardID = value;
            }
        }

        [NonSerialized]
        private bool _initialized;
        public bool Initialized
        {
            get { return _initialized; }
            set { _initialized = value; }
        }


        private int _inputCount = 24;
        public int InputCount
        {
            get
            {
                return _inputCount;
            }
            set
            {
                _inputCount = value;
            }

        }

        private int _outputCount = 24;
        public int OutputCount
        {
            get
            {
                return _outputCount;
            }
            set
            {
                _outputCount = value;
            }
        }

        private string _cardType = "UWC348A";
        public string CardType
        {
            get
            {
                return _cardType;
            }
            set
            {
                _cardType = value;
            }

        }





    }
}
